package yijy.example.MultiThread;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by yijy on 2017/8/8.
 */
public class DownLoadUtil{

    private String path;//目标路径

    private String targetPath;//存储路径

    private down[] threads;//启动线程组

    private int filesize;//目标文件大小

    private int threadNum;//线程数量

    public DownLoadUtil(String path,String targetPath, int threadNum){
        this.path=path;
        this.targetPath=targetPath;
        this.threadNum=threadNum;
        // 初始化threads数组
        threads=new down[threadNum];
    }

    public void down1(){
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5_000);
            conn.setRequestMethod("GET");
            conn.setRequestProperty(
                    "Accept",
                    "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                    + "application/x-shockwave-flash, application/xaml+xml, "
                    + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                    + "application/x-ms-application, application/vnd.ms-excel, "
                    + "application/vnd.ms-powerpoint, application/msword, */*");
            conn.setRequestProperty("Accept-Language", "zh-CN");
            conn.setRequestProperty("Charset", "UTF-8");

            filesize =  conn.getContentLength();
            conn.disconnect();
            int currentPartSize = filesize/threadNum +1;
            RandomAccessFile file = new RandomAccessFile(targetPath, "rw");
            //  设置本地文件的大小
            file.setLength(filesize);
            file.close();

            for(int i=0;i<threadNum;i++){
                //每个线程现在的起点
                int startPos = i*currentPartSize;
                // 每个线程使用一个RandomAccessFile进行下载
                RandomAccessFile raf = new RandomAccessFile(targetPath, "rw");
                raf.seek(startPos);//定位该线程的下载位置
                threads[i] = new down(startPos, currentPartSize, raf);
                threads[i].start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class down extends Thread{
        private int startPos;//从该节点开始下载

        private int currentSize;//当前线程需要下载的文件大小

        private int length;//该线程下载长度

        private RandomAccessFile raf;

        public down(int startPos,int currentSize,RandomAccessFile raf){
            this.startPos=startPos;
            this.currentSize=currentSize;
            this.raf = raf;
        }

        @Override
        public void run() {
            try {
                System.out.println(getName());
                URL url = new URL(path);
                HttpURLConnection conn =  (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5_000);
                conn.setRequestMethod("GET");
                conn.setRequestProperty(
                        "Accept",
                        "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                        + "application/x-shockwave-flash, application/xaml+xml, "
                        + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                        + "application/x-ms-application, application/vnd.ms-excel, "
                        + "application/vnd.ms-powerpoint, application/msword, */*");
                conn.setRequestProperty("Accept-Language", "zh-CN");
                conn.setRequestProperty("Charset", "UTF-8");

                InputStream is = conn.getInputStream();
                //  跳过startPos个字节，表明该线程只下载自己负责哪部分文件。
                is.skip(this.startPos);
                byte[] buff = new byte[2048];
                int hasread = 0;
                while(length<currentSize && (hasread=is.read(buff))!=-1){
                    raf.write(buff,0,hasread);
                    length +=hasread;
                }
                raf.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
